package com.sali.netty;

import com.sali.config.NettyConfig;
import com.sali.disruptor.MessageDisruptorService;
import com.sali.netty.handler.MockDecoder;
import com.sali.netty.handler.ServerHandle;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.ByteOrder;

/**
 * @description:
 * @author: sali
 * @date: 2025/2/22 下午1:38.
 * @version: 1.0
 */
@Component
@Slf4j
public class NettyServer {

    @Autowired
    private NettyConfig nettyConfig;

    @Resource
    private MessageDisruptorService messageDisruptorService;

    private NioEventLoopGroup bossGroup = null;

    private NioEventLoopGroup workerGroup = null;

    public void start() {
        if (nettyConfig.getBossGroup() != -1) {
            bossGroup = new NioEventLoopGroup(nettyConfig.getBossGroup());
        } else {
            bossGroup = new NioEventLoopGroup();
        }

        if (nettyConfig.getWorkerGroup() != -1) {
            workerGroup = new NioEventLoopGroup(nettyConfig.getWorkerGroup());
        } else {
            workerGroup = new NioEventLoopGroup();
        }

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    // 指定所使用的 NIO传输 Channel
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, nettyConfig.getSocketQueue())
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 添加一个handler到ChannelPipeline
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline()
                                    .addLast(new MockDecoder(ByteOrder.LITTLE_ENDIAN,65535, 0, 4, 0, 0,true))
                                    .addLast(new IdleStateHandler(30, 30, 90))
                                    .addLast(new ServerHandle(messageDisruptorService));
                        }
                    })
                    .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
            // 异步地绑定服务器；调用 sync()方法阻塞 等待直到绑定完成
            ChannelFuture f = bootstrap.bind(nettyConfig.getPort()).sync();
            log.info("netty server running......");
            // 获取 Channel 的CloseFuture，并且阻塞当前线程直到它完成
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("netty server run is error,msg:[message:{}]", e.getMessage(), e);
            Thread.currentThread().interrupt();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
